package eav_service

import (
	"context"
	"errors"
	"fmt"

	"rdiot-demo/internal/eav/domain"
	"rdiot-demo/internal/eav/repository"

	"github.com/google/uuid"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// templateService TemplateService的具体实现
type templateService struct {
	repo   repository.TemplateRepository
	logger *zap.Logger
}

// NewTemplateService 创建新的模板服务实例
func NewTemplateService(db *gorm.DB, logger *zap.Logger) TemplateService {
	repo := repository.NewTemplateRepository(db)
	return &templateService{
		repo:   repo,
		logger: logger,
	}
}

// CreateTemplate 创建实体模板
func (s *templateService) CreateTemplate(ctx context.Context, template *domain.EntityTemplate) error {
	s.logger.Info("Creating entity template", zap.String("name", template.Name))

	// 1. 数据验证
	if err := s.validateTemplate(template); err != nil {
		s.logger.Error("Template validation failed", zap.Error(err))
		return fmt.Errorf("validation failed: %w", err)
	}

	// 2. 检查名称是否已存在
	existing, err := s.repo.GetByName(ctx, template.Name)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		s.logger.Error("Failed to check template existence", zap.Error(err))
		return fmt.Errorf("failed to check template existence: %w", err)
	}

	if existing != nil {
		return fmt.Errorf("template with name '%s' already exists", template.Name)
	}

	// 3. 验证属性模板
	if err := s.validateAttributes(template.Attributes); err != nil {
		s.logger.Error("Attribute validation failed", zap.Error(err))
		return fmt.Errorf("attribute validation failed: %w", err)
	}

	// 4. 设置默认值
	template.IsActive = true

	// 5. 保存模板
	if err := s.repo.Create(ctx, template); err != nil {
		s.logger.Error("Failed to create template", zap.Error(err))
		return fmt.Errorf("failed to create template: %w", err)
	}

	s.logger.Info("Template created successfully",
		zap.String("id", template.ID.String()),
		zap.String("name", template.Name))

	return nil
}

// GetTemplate 获取指定ID的模板
func (s *templateService) GetTemplate(ctx context.Context, id uuid.UUID) (*domain.EntityTemplate, error) {
	s.logger.Debug("Getting template", zap.String("id", id.String()))

	if id == uuid.Nil {
		return nil, errors.New("template ID cannot be empty")
	}

	template, err := s.repo.GetByID(ctx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("template with ID '%s' not found", id.String())
		}
		s.logger.Error("Failed to get template", zap.String("id", id.String()), zap.Error(err))
		return nil, fmt.Errorf("failed to get template: %w", err)
	}

	return template, nil
}

// UpdateTemplate 更新模板
func (s *templateService) UpdateTemplate(ctx context.Context, template *domain.EntityTemplate) error {
	s.logger.Info("Updating template", zap.String("id", template.ID.String()))

	// 1. 验证模板ID
	if template.ID == uuid.Nil {
		return errors.New("template ID cannot be empty")
	}

	// 2. 检查模板是否存在
	existing, err := s.repo.GetByID(ctx, template.ID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("template with ID '%s' not found", template.ID.String())
		}
		return fmt.Errorf("failed to check template existence: %w", err)
	}

	// 3. 验证更新的数据
	if err := s.validateTemplate(template); err != nil {
		return fmt.Errorf("validation failed: %w", err)
	}

	// 4. 检查名称冲突（如果名称发生变化）
	if existing.Name != template.Name {
		nameExists, err := s.repo.GetByName(ctx, template.Name)
		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("failed to check name uniqueness: %w", err)
		}
		if nameExists != nil && nameExists.ID != template.ID {
			return fmt.Errorf("template with name '%s' already exists", template.Name)
		}
	}

	// 5. 验证属性模板
	if err := s.validateAttributes(template.Attributes); err != nil {
		return fmt.Errorf("attribute validation failed: %w", err)
	}

	// 6. 执行更新
	if err := s.repo.Update(ctx, template); err != nil {
		s.logger.Error("Failed to update template", zap.Error(err))
		return fmt.Errorf("failed to update template: %w", err)
	}

	s.logger.Info("Template updated successfully", zap.String("id", template.ID.String()))
	return nil
}

// DeleteTemplate 删除模板
func (s *templateService) DeleteTemplate(ctx context.Context, id uuid.UUID) error {
	s.logger.Info("Deleting template", zap.String("id", id.String()))

	if id == uuid.Nil {
		return errors.New("template ID cannot be empty")
	}

	// 1. 检查模板是否存在
	_, err := s.repo.GetByID(ctx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("template with ID '%s' not found", id.String())
		}
		return fmt.Errorf("failed to check template existence: %w", err)
	}

	// 2. 检查是否有关联的实体（这里暂时跳过，后续可以添加）
	// TODO: 检查是否有基于此模板创建的实体

	// 3. 执行删除
	if err := s.repo.Delete(ctx, id); err != nil {
		s.logger.Error("Failed to delete template", zap.Error(err))
		return fmt.Errorf("failed to delete template: %w", err)
	}

	s.logger.Info("Template deleted successfully", zap.String("id", id.String()))
	return nil
}

// ListTemplates 查询模板列表
func (s *templateService) ListTemplates(ctx context.Context, filter TemplateFilter) ([]domain.EntityTemplate, int64, error) {
	s.logger.Debug("Listing templates", zap.Any("filter", filter))

	// 设置默认分页参数
	if filter.Size <= 0 {
		filter.Size = 20
	}
	if filter.Size > 100 {
		filter.Size = 100 // 最大限制100条
	}
	if filter.Page < 1 {
		filter.Page = 1
	}

	templates, total, err := s.repo.List(ctx, repository.TemplateFilter{
		Name:     filter.Name,
		IsActive: filter.IsActive,
		Page:     filter.Page,
		Size:     filter.Size,
	})
	if err != nil {
		s.logger.Error("Failed to list templates", zap.Error(err))
		return nil, 0, fmt.Errorf("failed to list templates: %w", err)
	}

	s.logger.Debug("Templates listed successfully", zap.Int("count", len(templates)))
	return templates, total, nil
}

// validateTemplate 验证模板数据
func (s *templateService) validateTemplate(template *domain.EntityTemplate) error {
	if template == nil {
		return errors.New("template cannot be nil")
	}

	if template.Name == "" {
		return errors.New("template name is required")
	}

	if len(template.Name) > 100 {
		return errors.New("template name cannot exceed 100 characters")
	}

	return nil
}

// validateAttributes 验证属性模板列表
func (s *templateService) validateAttributes(attributes []domain.AttributeTemplate) error {
	if len(attributes) == 0 {
		return nil // 允许没有属性的模板
	}

	attributeNames := make(map[string]bool)
	for _, attr := range attributes {
		// 检查属性名称唯一性
		if attributeNames[attr.Name] {
			return fmt.Errorf("duplicate attribute name: %s", attr.Name)
		}
		attributeNames[attr.Name] = true

		// 验证属性字段
		if err := s.validateAttribute(attr); err != nil {
			return fmt.Errorf("invalid attribute '%s': %w", attr.Name, err)
		}
	}

	return nil
}

// validateAttribute 验证单个属性模板
func (s *templateService) validateAttribute(attr domain.AttributeTemplate) error {
	if attr.Name == "" {
		return errors.New("attribute name is required")
	}

	if len(attr.Name) > 100 {
		return errors.New("attribute name cannot exceed 100 characters")
	}

	if !s.isValidDataType(attr.DataType) {
		return fmt.Errorf("invalid data type: %s", attr.DataType)
	}

	return nil
}

// isValidDataType 检查数据类型是否有效
func (s *templateService) isValidDataType(dataType domain.DataType) bool {
	validTypes := []domain.DataType{
		domain.DataTypeString,
		domain.DataTypeNumber,
		domain.DataTypeBoolean,
		domain.DataTypeDatetime,
		domain.DataTypeReference,
		domain.DataTypeArray,
		domain.DataTypeJSON,
	}

	for _, validType := range validTypes {
		if dataType == validType {
			return true
		}
	}

	return false
}
